package com.panopset.gui.container;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

import com.panopset.java.Version;

/**
 * Panopset numeric only field.
 *
 * @author Karl Dinwiddie
 *
 */
public class PanNumericOnlyField extends PanTextField {

    /**
     * @param cols
     *            Columns.
     * @param borderTitle
     *            Border title.
     * @param toolTipText
     *            Tool tip text.
     * @param defaultValue
     *            Default value.
     */
    public PanNumericOnlyField(final int cols, final String borderTitle,
            final String toolTipText, final String defaultValue) {
        super(cols, borderTitle, toolTipText, defaultValue);
        getInnerComponent().setDocument(new NumberFilterDocument());
    }

    /**
     * Number filter document inner class.
     *
     * <h5>References</h5>
     * <ul>
     * <li>
     * <a href="from http://www.devx.com/tips/Tip/25194"> from
     * http://www.devx.com/tips/Tip/25194</a></li>
     * </ul>
     *
     */
    private static final class NumberFilterDocument extends PlainDocument {

        /**
         * Scratch buffer.
         */
        private StringBuffer scratchBuffer;

        /**
         * Constructor.
         */
        public NumberFilterDocument() {
            scratchBuffer = new StringBuffer();
        }

        /**
         * Insert string.
         * @param offset Offset.
         * @param text Text.
         * @param aset Attribute set.
         * @throws BadLocationException Bad location exception.
         */
        public void insertString(final int offset, final String text,
                final AttributeSet aset) throws BadLocationException {
            if (text == null) {
                return;
            }

            scratchBuffer.setLength(0);

            // Reject all strings that cause the contents of the field not
            // to be a valid number (i.e., string representation of a double)
            try {
                scratchBuffer.append(getText(0, getLength()));
                scratchBuffer.insert(offset, text);
                // Kludge: Append a 0 so that leading decimal points
                // and signs will be accepted
                scratchBuffer.append('0');
            } catch (BadLocationException ble) {
                ble.printStackTrace();
                return;
            } catch (StringIndexOutOfBoundsException sioobe) {
                sioobe.printStackTrace();
                return;
            }

            try {
                Double.parseDouble(scratchBuffer.toString());
            } catch (NumberFormatException nfe) {
                // Resulting string will not be number, so reject it
                return;
            }

            super.insertString(offset, text, aset);
        }

        /**
         * Serial verion id.
         */
        private static final long serialVersionUID
            = Version.UNI_VERSION;
    }
}
